package com.hb.B_面向对象.D_伴生对象_object

import java.util.*
import java.util.stream.Collectors
import kotlin.Comparator

/**
 * kotlin中，将告别java中的static关键字。引入了全新的关键字object,可以
 * 完美的代替使用static的所有场景。object还具有单例对象以及简化匿名表达式的功能。
 *
 * 伴生对象的解析：
 *  "伴生"是相较于一个类来说的，意味着伴随某个类的对象，它属于这个类的所有，因此
 *  伴生对象和java中的static修饰效果性质一样，全局只有一个单例，他需要声明在类
 *  的内部，在类被装载时会被初始化。
 *
 *  一个类的伴生对象和一个静态类一样，全局只能有有一个===》单例对象
 */
fun main() {
    val prize = Prize("红包", 10, Prize.TYPE_READPACK)
    println(Prize.isReadPack(prize))//true

    //修改DatabaseConfig的属性
    DatabaseConfig.password = "678"
    println("DatabaseConfig.password = ${DatabaseConfig.password}")//DatabaseConfig.password = 678

    val databaseConfig1:DatabaseConfig= DatabaseConfig
    val databaseConfig2:DatabaseConfig= DatabaseConfig
    //true 说明是单例的。
    println("databaseConfig1 == databaseConfig2 ="+(databaseConfig1 == databaseConfig2))


    //object实现的匿名内部类
    /**
     * object表达式和java的匿名内部类很相似，但是我们发现，object表达式可以赋值给一个变量
     * 这在我们重复使用的时候将会减少很多代码。另外，我们说过object可以继承类和实现接口，匿名内部类
     * 只能继承一个类及实现一个接口，而object表达式却没有这个限制。
     *
     * 用于代替匿名内部类的object表达式在运行中不像我们在单例模式中说的那样，全局只存在一个对象，而是在每次运行
     * 时都会生成一个新的对象。
     *
     * 对象表达式和lambda表达式那个更适合代替匿名内部类？
     * 当你的匿名内部类使用的类接口只需要实现一个方法的时候，使用lambda表达式更适合。
     * 当匿名内部类内有多个方法实现的时候，使用object表达式更加适合。
     */
    //表示object去继承的Comparator类
    val comparator=object :Comparator<String>{
        override fun compare(o1: String?, o2: String?): Int {
             if (o1==null)
                 return -1
             else if (o2==null)
                 return 1
             return o1.compareTo(o2)
        }
    }

    val listOf = mutableListOf("abc","bbc")
    Collections.sort(listOf,comparator)

}

class Prize(val name: String, val count: Int, val type: Int) {
    companion object {
        val TYPE_READPACK = 0
        val TYPE_COUPON = 1
        fun isReadPack(prize: Prize): Boolean {
            return prize.type == TYPE_READPACK
        }
    }
}

/**
 * 在kotlin中，由于object的存在，我们可以直接用它来实现单例
 *
 * 由于object全局声明的对象只用一个，所以他并不需要语法上的初始化，甚至都不需要构造方法。因此
 * 我们可以说object创造的是天生的单例，我们并不需要再kotlin中去构建一个类似java的单例模式。
 * 由于DatabaseConfig的属性是用var声明的String,我们还可以修改他们：
 *
 *
 * 单例也可以和普通类一样实现接口和继承类，所以你可以将他看成一种不需要我们主动初始化的类。单例
 * 对象会在系统加载的时候初始化，当然全局就只有一个。
 *
 * object的作用：
 *  1. 单例对象
 *  2. 代替java中的匿名内部类
 * */
object DatabaseConfig {
    var host: String = "127.0.0.1"
    var port: Int = 3306
    var username: String = "root"
    var password: String = "123"
}




